<?php

namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\base\Exception;
use app\models\SysConfig;
use app\models\ChargeCashDeal;
use yii\filters\AccessControl;
use app\models\Member;
use yii\helpers\Json;
class PayController extends \yii\web\Controller
{
    public function beforeAction($action)
   {
     $this->enableCsrfValidation = false;
     //检查是否允许登录
     return parent::beforeAction($action);
   }

    public function actionIndex()
    {
        return $this->render('index');
    }
    /*
    payease 支付订单支付结果返回页面接口处理（首信易支付-》商户 必作接口）
    //用户为首信易网关机器人
    */
      public function actionPayeasertn()
      {
        $this->layout='payrtn';
        $md5info_verify=0;
        $md5money_verify=0;
        $proc_error_string='';

        //get处理
        //请求参数有
        //v_url
        $v_oid=Yii::$app->request->get('v_oid');
        $v_pmode=Yii::$app->request->get('v_pmode');
        //v_pstatus
        $v_pstatus=Yii::$app->request->get('v_pstatus');
        //v_pstring
        $v_pstring=Yii::$app->request->get('v_pstring');
        //v_md5info (v_oid,v_pstatus,v_pstring,v_pmode)
        $v_md5info=Yii::$app->request->get('v_md5info');
        //验证v_md5info
        $src_string=$v_oid.$v_pstatus.$v_pstring.$v_pmode;

        $sysconfig=SysConfig::getSysConfig();


        $MD5Key=$sysconfig->sxy_key;
        //win32
        exec(Yii::getAlias("@app").'/payment/payease/md5/win32/MD5Win32 "'.$src_string.'" "'.$MD5Key.'"',$MD5Result,$res);
        //linux
        //exec(Yii::getAlias("@app").'/payment/payease/md5/linux/sample "'.$src_string.'" "'.$MD5Key.'"',$MD5Result,$res);

        $sign='';
        if($res==0){
          $sign=$MD5Result[0];
        }

        if($sign!=$v_md5info){
          $md5info_verify=1;
        }
        //v_amount
        $v_amount=Yii::$app->request->get('v_amount');
        //v_moneytype
        $v_moneytype=Yii::$app->request->get('v_moneytype');
        //v_md5money(v_amount,v_moneytype)
        $v_md5money=Yii::$app->request->get('v_md5money');
        //验证v_md5money
        $src_string2=$v_amount.$v_moneytype;
        $MD5Key2=$sysconfig->sxy_key;
        //win32
        exec(Yii::getAlias("@app").'/payment/payease/md5/win32/MD5Win32 "'.$src_string2.'" "'.$MD5Key2.'"',$MD5Result2,$res2);
        //linux
        //exec(Yii::getAlias("@app").'/payment/payease/md5/linux/sample "'.$src_string2.'" "'.$MD5Key2.'"',$MD5Result2,$res2);

        $sign2='';
        if($res2==0){
          $sign2=$MD5Result2[0];
        }
        if($sign2!=$v_md5money){
          $md5money_verify=1;
        }
        //v_sign(v_oid,v_pstatus,v_amount,v_moneytype)
        $v_sign=Yii::$app->request->get('v_sign');



        if(($md5info_verify==0)&&($md5money_verify==0)){
          if($v_pstatus==1){
            //更新到数据库
            $tr=Yii::$app->db->beginTransaction();
            try{
              //充值登记与计算
              if(is_null($sysconfig)){
                throw new Exception('无法取得汇率和充值返回比例。');
              }

              //1.记录充值结果
              $ok=ChargeCashDeal::payeaseCongzhiProve($v_oid,ChargeCashDeal::STATUS_PROVED);
              if(!$ok){
                //记录充值结果不成功
                  throw new Exception('记录充值结果不成功。'.$v_oid);
              }

              //充值返还
              //2.计算实际到账金额
              $realmoney=($v_amount+$v_amount*$sysconfig->congzhi_reward)/$sysconfig->exchange_rate;

              //3.进行用户账面划拨
              $model = ChargeCashDeal::find()->where([
                'orderno'=>$v_oid
                ])->One();
              if(is_null($model)){
                throw new Exception('订单不存在。'.$v_oid);
              }
              if(!Member::congzhi($model->member_id,$realmoney)){
                throw new Exception('用户充值账面划拨失败。'.$v_oid);
              }

              //4.计算推荐奖
              if(Member::isFirstCharge($model->member_id)){
                $member = Member::findOne($model->member_id);
                if($member){
                  $tjr = Member::findByMemberName2($member->tjr);
                  if($tjr){
                    if($tjr->id!=$sysconfig->administrator){
                      $tuijian_reward = $v_amount*$sysconfig->tjj_rate/$sysconfig->exchange_rate;
                      Member::tuijian($tjr,$tuijian_reward);
                    }
                  }
                }
              }
              $tr->commit();
            }catch(Exception $e){
              $proc_error_string = $e->getMessage();
              $tr->rollBack();
            }
          }else if($v_pstatus==20){
            //更新到数据库
            $tr=Yii::$app->db->beginTransaction();
            try{
              //充值登记与计算

              if(is_null($sysconfig)){
                throw new Exception('无法取得汇率和充值返回比例。'.$v_oid);
              }

              //1.记录充值结果
              $ok=ChargeCashDeal::payeaseCongzhiProve($v_oid,ChargeCashDeal::STATUS_PROVED);
              if(!$ok){
                //记录充值结果不成功
                  throw new Exception('记录充值结果不成功。'.$v_oid);
              }

              //充值返还
              //2.计算实际到账金额
              $realmoney=($v_amount+$v_amount*$sysconfig->congzhi_reward)/$sysconfig->exchange_rate;

              //3.进行用户账面划拨
              $model = ChargeCashDeal::find()->where([
                'orderno'=>$v_oid
                ])->One();
              if(is_null($model)){
                throw new Exception('订单不存在。'.$v_oid);
              }
              if(!Member::congzhi($model->member_id,$realmoney)){
                throw new Exception('用户充值账面划拨失败。'.$v_oid);
              }

              //4.计算推荐奖
              if(Member::isFirstCharge($model->member_id)){
                $member = Member::findOne($model->member_id);
                if($member){
                  $tjr = Member::findByMemberName2($member->tjr);
                  if($tjr){
                    if($tjr->id!=$sysconfig->administrator){
                      $tuijian_reward = $v_amount*$sysconfig->tjj_rate/$sysconfig->exchange_rate;
                      Member::tuijian($tjr,$tuijian_reward);
                    }
                  }
                }
              }
              $tr->commit();
            }catch(Exception $e){
              $proc_error_string = $e->getMessage();
              Yii::getLogger()->log($proc_error_string,yii\log\Logger::LEVEL_ERROR,'MyLog');
              $tr->rollBack();
            }
          }else if($v_pstatus==30){

              //1.记录充值结果
              $ok=ChargeCashDeal::payeaseCongzhiProve($v_oid,ChargeCashDeal::STATUS_UNPROVED);
              if(!$ok){
                //记录充值结果不成功
                  $proc_error_string='记录充值结果不成功。';
              }
          }else{

          }
        }else{
          //签名验证不成功
          return;
        }
        return $this->render('payeasertn',[
          'v_oid'=>$v_oid,
          //v_pmode
          'v_pmode'=>Yii::$app->request->get('v_pmode'),
          //v_pstatus
          'v_pstatus'=>Yii::$app->request->get('v_pstatus'),
          //v_pstring
          'v_pstring'=>Yii::$app->request->get('v_pstring'),
          //v_md5info (v_oid,v_pstatus,v_pstring,v_pmode)
          'v_md5info'=>Yii::$app->request->get('v_md5info'),
          //v_amount
          'v_amount'=>Yii::$app->request->get('v_amount'),
          //v_moneytype
          'v_moneytype'=>Yii::$app->request->get('v_moneytype'),
          //v_md5money(v_amount,v_moneytype)
          'v_md5money'=>Yii::$app->request->get('v_md5money'),
          //v_sign(v_oid,v_pstatus,v_amount,v_moneytype)
          'v_sign'=>Yii::$app->request->get('v_sign'),
          'md5info_verify'=>$md5info_verify,
          'md5money_verify'=>$md5money_verify,
          'proc_error_string'=>$proc_error_string
        ]);
      }
      /**
       * 微信扫码支付返回地址
       *
       * @return string
       */
      public function actionWeixinrtn()
      {
          $tr=Yii::$app->db->beginTransaction();
          try{
            //获取通知的数据(从xml-rpc获取数据)
    		    $xml = file_get_contents('php://input');
            if(!$xml){
              throw new Exception("xml数据异常！");
            }
            //将XML转为array
            //禁止引用外部xml实体
            libxml_disable_entity_loader(true);
            $result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            if($result['return_code'] != 'SUCCESS'){
              throw new Exception("return_code不为SUCCESS！");
  		      }

            //验证签名
            if(!array_key_exists('sign', $result)){
              throw new Exception("签名错误！");
            }
            //签名步骤一：按字典序排序参数
            ksort($result);

            $buff = "";
            foreach ($result as $k => $v)
            {
              if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
              }
            }
            $buff = trim($buff, "&");

            //签名步骤二：在string后加入KEY
            $sysconfig = SysConfig::getSysConfig();
            if(is_null($sysconfig)){
              throw new Exception("无法获得系统配置。");
            }
            $buff = $buff . "&key=".$sysconfig->weixin_ipakey;
            //签名步骤三：MD5加密
            $buff = md5($buff);
            //签名步骤四：所有字符转为大写
            $buff = strtoupper($buff);
            if($result['sign']!=$buff){
              throw new Exception("签名不匹配！");
            }

            //返回消息

          	$notfiyOutput = array();

          	if(!array_key_exists("transaction_id", $result)){
          			throw new Exception("输入参数不正确！");
          	}
          	//查询订单，判断订单真实性
          	/*if(!$this->Queryorder($data["transaction_id"])){
          			throw new Exception("订单查询失败。");
          	}*/
            //交易成功

            if(!array_key_exists("out_trade_no", $result)){
              throw new Exception("输入参数不正确！");
            }
            //查询本地记录
            $local_trade_no = $result['out_trade_no'];
            $deal = ChargeCashDeal::find()->where(
              ['orderno'=>$local_trade_no]
              )->one();
            if(is_null($deal)){
              throw new Exception("订单不存在！".$local_trade_no);
            }

            //查询订单是否存在
            $url = "https://api.mch.weixin.qq.com/pay/orderquery";
            $nonce_str = Member::generateRandom(24);

            $stringA='';
            $stringA.='appid=';
            $stringA.=$sysconfig->weixin_appid;
            $stringA.='&mch_id=';
            $stringA.=$sysconfig->weixin_businessid;
            $stringA.='&nonce_str=';
            $stringA.=$nonce_str;   //使用自定义的24位随机数算法
            $stringA.='&transaction_id=';
            $stringA.=$result['transaction_id'];

            //md5计算sign
            $stringSignTemp=$stringA.'&key='.$sysconfig->weixin_ipakey;

            //echo $stringSignTemp;
            //echo "<br>";
            $sign = md5($stringSignTemp);
            $sign = strtoupper($sign);

            $paraXml='<?xml version="1.0" encoding="UTF-8"?>';
            $paraXml.='<xml>';
            $paraXml.='<appid><![CDATA[';
            $paraXml.=$sysconfig->weixin_appid;
            $paraXml.=']]></appid>';
            $paraXml.='<mch_id><![CDATA[';
            $paraXml.=$sysconfig->weixin_businessid;
            $paraXml.=']]></mch_id>';
            $paraXml.='<nonce_str><![CDATA[';
            $paraXml.=$nonce_str;   //使用自定义的24位随机数算法
            $paraXml.=']]></nonce_str>';
            $paraXml.='<transaction_id><![CDATA[';
            $paraXml.=$result['transaction_id'];
            $paraXml.=']]></transaction_id>';
            $paraXml.='<sign><![CDATA[';
            $paraXml.=$sign;
            $paraXml.=']]></sign>';
            $paraXml.='</xml>';
            //echo $paraXml;
            //echo '<br>';
            $ch = curl_init();
            //设置超时30s
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch,CURLOPT_URL, "https://api.mch.weixin.qq.com/pay/orderquery");
            //ssl验证身份
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
            //设置header
            curl_setopt($ch, CURLOPT_HEADER, FALSE);
            //要求结果为字符串且输出到屏幕上
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            //post提交方式
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $paraXml);
            //运行curl
            $data = curl_exec($ch);
            //返回结果
            if($data){
              curl_close($ch);
            } else {
              $error = curl_errno($ch);
              curl_close($ch);
              throw new Exception("curl出错，错误码:$error");
            }
            //echo $data;
            if(!$data){
              throw new Exception("予下单返回xml数据异常！");
            }
                //将XML转为array
                //libxml_disable_entity_loader()作用是设置是否禁止从外部加载XML实体，设为true就是禁止，目的是防止XML注入攻击
            libxml_disable_entity_loader(true);
            $result2 = json_decode(json_encode(simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            if(array_key_exists("return_code", $result2)
        			&& array_key_exists("result_code", $result2)
        			&& $result2["return_code"] == "SUCCESS"
        			&& $result2["result_code"] == "SUCCESS")
        		{

              //$tr=Yii::$app->db->beginTransaction();
              //try{
                //充值登记与计算
                //1.记录充值结果
                $ok=ChargeCashDeal::weixinCongzhiProve($local_trade_no,ChargeCashDeal::STATUS_PROVED);
                if(!$ok){
                  //记录充值结果不成功
                    throw new Exception('记录微信充值结果不成功。'.$local_trade_no);
                }

                //充值返还
                $v_amount=$deal->money;
                //2.计算实际到账金额
                $realmoney=($v_amount+$v_amount*$sysconfig->congzhi_reward)/$sysconfig->exchange_rate;

                //3.进行用户账面划拨
                $model = ChargeCashDeal::find()->where([
                  'orderno'=>$local_trade_no
                  ])->One();
                if(is_null($model)){
                  throw new Exception('订单不存在。'.$local_trade_no);
                }
                if(!Member::congzhi($model->member_id,$realmoney)){
                  throw new Exception('用户充值账面划拨失败。'.$local_trade_no);
                }

                //4.计算推荐奖
                if(Member::isFirstCharge($model->member_id)){
                  $member = Member::findOne($model->member_id);
                  if($member){
                    $tjr = Member::findByMemberName2($member->tjr);
                    if($tjr){
                      if($tjr->id!=$sysconfig->administrator){
                        $tuijian_reward = $v_amount*$sysconfig->tjj_rate/$sysconfig->exchange_rate;
                        Member::tuijian($tjr,$tuijian_reward);
                      }
                    }
                  }
                }
                $tr->commit();
              /*}catch(Exception $e){
                $proc_error_string = $e->getMessage();
                Yii::getLogger()->log($proc_error_string,yii\log\Logger::LEVEL_ERROR,'MyLog');
                $tr->rollBack();
              }*/

               $outrtn='<?xml version="1.0" encoding="UTF-8"?>';
               $outrtn.='<xml>';
               $outrtn.='<return_code><![CDATA[';
               $outrtn.='SUCCESS';
               $outrtn.=']]></return_code>';
               $outrtn.='<return_msg><![CDATA[';
               $outrtn.='OK';
               $outrtn.=']]></return_msg>';
               $outrtn.='</xml>';
               echo $outrtn;
               return;
        		}
            $outrtn='<?xml version="1.0" encoding="UTF-8"?>';
            $outrtn.='<xml>';
            $outrtn.='<return_code><![CDATA[';
            $outrtn.='FAIL';
            $outrtn.=']]></return_code>';
            $outrtn.='<return_msg><![CDATA[';
            $outrtn.='查询订单返回错误';
            $outrtn.=']]></return_msg>';
            $outrtn.='</xml>';
            echo $outrtn;

          }catch(Exception $e){
            //yii记录日志
            $tr->rollBack();
            Yii::getLogger()->log($e->getMessage(),yii\log\Logger::LEVEL_ERROR,'MyLog');
            $outrtn='<?xml version="1.0" encoding="UTF-8"?>';
            $outrtn.='<xml>';
            $outrtn.='<return_code><![CDATA[';
            $outrtn.='FAIL';
            $outrtn.=']]></return_code>';
            $outrtn.='<return_msg><![CDATA[';
            $outrtn.=$e->getMessage();
            $outrtn.=']]></return_msg>';
            $outrtn.='</xml>';
            echo $outrtn;

            return;
          }
      }

/*
* return 0: 充值返回成功
* return 1: 充值返回失败
* return 2: 等待充值返回
* return 3: 发生错误
*/
      public function actionQuerycongzhiresultajax(){
        if(Yii::$app->request->isAjax){
          $model=ChargeCashDeal::find()
          ->where(
            ['orderno'=>Yii::$app->request->get('orderno')]
            )->One();
          if(is_null($model)){
            echo Json::encode(array('errcode'=>3,'errmsg'=>'发生错误，没有充值订单。'));
            return;
          }
          switch($model->status){
            case ChargeCashDeal::STATUS_REGISTER:
            echo Json::encode(array('errcode'=>2,'errmsg'=>'等待充值结果返回。'));
            return;
            break;
            case ChargeCashDeal::STATUS_PROVED:
            echo Json::encode(array('errcode'=>0,'errmsg'=>'充值成功。'));
            return;
            break;
            case ChargeCashDeal::STATUS_UNPROVED:
            echo Json::encode(array('errcode'=>1,'errmsg'=>'充值失败。'));
            return;
            break;
            case ChargeCashDeal::STATUS_DISCARD:
            echo Json::encode(array('errcode'=>2,'errmsg'=>'等待充值结果返回。'));
            return;
            break;
            default:
            echo Json::encode(array('errcode'=>3,'errmsg'=>'发生错误，无法识别订单状态。'));
            return;
            break;
          }
          echo Json::encode(array('errcode'=>3,'errmsg'=>'发生错误。'));
        }
      }
}
